﻿using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Data.Entity;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Derbster.Domain;

namespace Derbster.Data
{
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1063:ImplementIDisposableCorrectly")]
    public class DerbsterDbContext : DbContext, IDerbsterContext
    {
        public DerbsterDbContext()
            : base()
        {
            InitializeInternalDbSets();
        }

        public DerbsterDbContext(string nameOrConnectionString)
            : base(nameOrConnectionString)
        {
            InitializeInternalDbSets();
        }

        public DerbsterDbContext(DbConnection existingConnection, bool contextOwnsConnection)
            : base(existingConnection, contextOwnsConnection)
        {
            InitializeInternalDbSets();
        }

        private void InitializeInternalDbSets()
        {
            BoxEvents = Set<BoxEvent>();
            Jams = Set<Jam>();
            Lineups = Set<Lineup>();
            OfficialRosters = Set<OfficialRoster>();
            Penalties = Set<Penalty>();
            Players = Set<Player>();
            RosteredOfficials = Set<RosteredOfficial>();
            Scoring = Set<Scoring>();
            ScoringPasses = Set<ScoringPass>();
        }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Entity<BoxEvent>().HasRequired(be => be.Player).WithMany();

            modelBuilder.Entity<Jam>()
                .HasRequired(j => j.FirstTeamLineup)
                .WithOptional()
                .Map(m=>m.MapKey("FirstLineupId"))
                .WillCascadeOnDelete(false);
            modelBuilder.Entity<Jam>().HasRequired(j => j.SecondTeamLineup)
                .WithOptional()
                .Map(m=>m.MapKey("SecondLineupId"))
                .WillCascadeOnDelete(false);
            modelBuilder.Entity<Jam>()
                .HasRequired(j => j.FirstTeamScoring)
                .WithOptional()
                .Map(m => m.MapKey("FirstScoringId"))
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<Jam>()
                .HasRequired(j => j.SecondTeamScoring)
                .WithOptional()
                .Map(m => m.MapKey("SecondScoringId"))
                .WillCascadeOnDelete(false);
                
            modelBuilder.Entity<League>().HasMany(l => l.Teams).WithOptional(t => t.League);
            modelBuilder.Entity<Lineup>().HasOptional(l => l.Jammer).WithMany();
            modelBuilder.Entity<Lineup>().HasOptional(l => l.Pivot).WithMany();
            modelBuilder.Entity<Lineup>().HasMany(l => l.Blockers).WithMany();

            modelBuilder.Entity<Match>()
                .HasRequired(m => m.FirstTeamRoster)
                .WithOptional()
                .Map(m => m.MapKey("FirstRosterId"))
                .WillCascadeOnDelete(false);
            modelBuilder.Entity<Match>()
                .HasRequired(m => m.SecondTeamRoster)
                .WithOptional()
                .Map(m => m.MapKey("SecondRosterId"))
                .WillCascadeOnDelete(false);

            modelBuilder.Entity<Match>().HasOptional(m => m.OfficialRoster).WithMany();
            modelBuilder.Entity<Match>().HasMany(m => m.Jams).WithRequired(j => j.Match).WillCascadeOnDelete(true);
            modelBuilder.Entity<Match>().HasMany(m => m.Penalties).WithRequired(p=>p.Match).WillCascadeOnDelete(true);
            modelBuilder.Entity<Match>().HasMany(m => m.BoxEvents).WithRequired(p=>p.Match).WillCascadeOnDelete(true);

            modelBuilder.Entity<Official>().HasOptional(o => o.League).WithMany();

            modelBuilder.Entity<OfficialRoster>().HasMany(or => or.NonSkatingOfficials);
            modelBuilder.Entity<OfficialRoster>().HasMany(or => or.SkatingOfficials);
            
            modelBuilder.Entity<Player>().HasRequired(p => p.Skater).WithMany();

            modelBuilder.Entity<Roster>().HasMany(r => r.Players).WithRequired(p=>p.Roster).WillCascadeOnDelete(true);

            modelBuilder.Entity<RosteredOfficial>().HasRequired(ro => ro.Official).WithMany();

            modelBuilder.Entity<Scoring>().HasMany(s => s.Passes).WithRequired(p=>p.Scoring);

            modelBuilder.Entity<ScoringPass>().HasRequired(sp => sp.Scoring).WithMany(s=>s.Passes);

            modelBuilder.Entity<Team>().HasMany(t => t.Skaters).WithMany();
        }

        internal IDbSet<BoxEvent> BoxEvents { get; set; }
        internal IDbSet<Jam> Jams { get; set; }
        public IDbSet<League> Leagues { get; set; }
        public IDbSet<Lineup> Lineups { get; set; }
        public IDbSet<Match> Matches { get; set; }
        public IDbSet<Official> Officials { get; set; }
        internal IDbSet<OfficialRoster> OfficialRosters { get; set; }
        internal IDbSet<Penalty> Penalties { get; set; }
        internal IDbSet<Player> Players { get; set; }
        public IDbSet<Roster> Rosters { get; set; }
        internal IDbSet<RosteredOfficial> RosteredOfficials { get; set; }
        internal IDbSet<Scoring> Scoring { get; set; }
        internal IDbSet<ScoringPass> ScoringPasses { get; set; }
        public IDbSet<Skater> Skaters { get; set; }
        public IDbSet<Team> Teams { get; set; }
        
    }
}
